package com.newlink.building.common_base.utils

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Build
import android.os.VibrationEffect.*
import android.os.Vibrator
import androidx.annotation.RequiresApi
import com.newlink.building.common_base.constant.Base_Constant

/**
 * @Author: Jake
 * @Date: 2024-03-25
 * @Description:
 */
class ShakeManager private constructor(var context: Context) : SensorEventListener {


//    private var context: Context

    private var intervalTimeMillis: Long = 0
    private var thresholdCount: Int = 0

    private var isOpenVibrator: Boolean = false
    private var shakeThreshold: Int = 0
    private var rotateThreshold: Float = 0f

    private lateinit var mSensorManager: SensorManager
    private var accelerometer: Sensor? = null
    private var gyroscope: Sensor? = null
    private var lastGyro: Float = 0.0f
    private var mVibrator: Vibrator? = null // 震动

    private var mOnShakeListener: OnShakeListener? = null

    private var lastShakeTime: Long = 0 // 上一次摇晃的时间
    private var shakeCount: Int = 0 // 摇晃计数

    private var shakeLevel: Int by Base_Preference(Base_Constant.SHAKE_LEVEL, 2)

    companion object {
        private const val GYRO_THRESHOLD = 6.5f

        @Volatile
        private var instance: ShakeManager? = null

        fun getInstance(context: Context): ShakeManager {
            return instance ?: synchronized(this) {
                instance ?: ShakeManager(context).also { instance = it }
            }
        }
    }

    fun initShakeParam() {
        this.intervalTimeMillis = 1800
        this.thresholdCount = 2

        this.shakeThreshold = when (shakeLevel) {
            0 -> 12
            1 -> 18
            2 -> 22
            3 -> 28
            else -> 38
        }

        this.rotateThreshold = when (shakeLevel) {
            0 -> 3.5f
            1 -> 4.5f
            2 -> 5.5f
            3 -> 6.5f
            else -> 8.5f
        }

        this.isOpenVibrator = true

        initShake()

    }

//    constructor(context: Context, intervalTimeMillis:Long = 1800,
//                thresholdCount:Int = 2, shakeThreshold:Int = 18,
//                isOpenVibrator:Boolean = false ) {
//        this.context = context
//        this.intervalTimeMillis = intervalTimeMillis
//        this.thresholdCount = thresholdCount
//
//        this.shakeThreshold = when (shakeLevel) {
//            0 -> 12
//            1 -> 18
//            2 -> 22
//            3 -> 28
//            else -> 38
//        }
//
//        this.rotateThreshold = when (shakeLevel) {
//            0 -> 3.5f
//            1 -> 4.5f
//            2 -> 5.5f
//            3 -> 6.5f
//            else -> 8.5f
//        }
//
//        this.isOpenVibrator = isOpenVibrator
//
//        initShake()
//    }

    private fun initShake() {
        NLog.e("[BLE] mShakeManager initShake ")
        mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        gyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)

        if (isOpenVibrator) {
            mVibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
        }

//        mSensorManager.registerListener(
//            this,
//            accelerometer,
//            SensorManager.SENSOR_DELAY_NORMAL
//        )

        accelerometer?.also { accel ->
            mSensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL)
        }

        gyroscope?.also { gyro ->
            mSensorManager.registerListener(this, gyro, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    interface OnShakeListener {
        fun onShake(isSuccess: Boolean)
    }

    fun setOnShakeListener(listener: OnShakeListener) {
        this.mOnShakeListener = listener
    }

    fun releaseShake() {
        if (isOpenVibrator) {
            mVibrator?.cancel()
            mVibrator = null
        }

        mSensorManager.unregisterListener(this)
        accelerometer = null
        gyroscope = null
        mOnShakeListener = null

    }

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onSensorChanged(event: SensorEvent) {
        // 加速器变更事件
        if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
            val values = event.values
            if (values[0] > shakeThreshold || values[1] > shakeThreshold || values[2] > shakeThreshold) {
                val currentTime = System.currentTimeMillis()
                // 忽略掉间隔时间小于intervalTimeMillis的摇晃事件
                if (currentTime - lastShakeTime < intervalTimeMillis) {
                    NLog.e("----shake block----")
                    return
                }

                shakeCount++
                NLog.e("----shake start count----$shakeCount")
                NLog.e("ShakeManager instance: ${this.hashCode()}")
                if (shakeCount >= thresholdCount) {
                    lastShakeTime = currentTime
                    if (isOpenVibrator) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                            mVibrator?.vibrate(createPredefined(EFFECT_DOUBLE_CLICK))
                        } else {
                            mVibrator?.vibrate(1500)
                        }
                    }
                    shakeCount = 0
                    lastShakeTime = 0
                    NLog.e("----TYPE_ACCELEROMETER----")
                    mOnShakeListener?.onShake(true)
                }
            }
        } else if (event.sensor.type == Sensor.TYPE_GYROSCOPE) {
            val rotationRate = kotlin.math.sqrt(
                (event.values[0] * event.values[0] +
                        event.values[1] * event.values[1] +
                        event.values[2] * event.values[2]).toDouble()
            ).toFloat()

            if (rotationRate - lastGyro > rotateThreshold) {
                val currentTime = System.currentTimeMillis()
                // 忽略掉间隔时间小于intervalTimeMillis的摇晃事件
                if (currentTime - lastShakeTime < intervalTimeMillis) {
                    NLog.e("----shake block----")
                    return
                }
                NLog.e("----TYPE_GYROSCOPE----")
                lastShakeTime = currentTime
                if (isOpenVibrator) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        mVibrator?.vibrate(createPredefined(EFFECT_DOUBLE_CLICK))
                    } else {
                        mVibrator?.vibrate(1500)
                    }
                }
                mOnShakeListener?.onShake(true)
                lastShakeTime = 0
                lastGyro = 0.0f
                return
            }
            lastGyro = rotationRate
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
    }
}